<template>
  <!-- #ifdef APP-NVUE -->
  <table></table>
  <!-- #endif -->
  <!-- #ifndef APP-NVUE -->
  <view>
    <view class="flex flex-row" v-if="_showHeader">
      <!-- 头固定1 -->
      <view v-if="_fixed.length > 0 && defaultProps.showFixed">
        <tm-sheet
          :border="_showBottomBorder ? 1 : 0"
          border-direction="bottom"
          :color="_fixed[0].bgColor"
          :text="_fixed[0].light"
          :_class="'flex flex-col ' + _fixed[0].align"
          :height="defaultProps.headerHeight - 6"
          :width="_fixed[0].width - 10"
          :margin="[0, 0]"
          :padding="[10, 6]"
          @click="headerClick(_fixed[0].key, _fixed[0].sort)"
        >
          <view
            :style="{
              width: _fixed[0].width - 10 + 'rpx',
              height: defaultProps.headerHeight - 6 + 'rpx',
            }"
            class="flex flex-row-center-center flex-row"
            :class="[_fixed[0].align]"
          >
            <view>
              <tm-text
                :font-size="26"
                _class="text-weight-b text-align-center"
                :label="_fixed[0].title"
              >
              </tm-text>
            </view>
            <view v-if="_fixed[0].sort" class="flex flex-col flex-col-center-center">
              <tm-icon
                :lineHeight="11"
                :_class="
                  _fixed[0].sortType == 'asce' || _fixed[0].sortType == 'none'
                    ? ''
                    : 'opacity-6'
                "
                :font-size="20"
                name="tmicon-sort-up"
              ></tm-icon>
              <tm-icon
                :lineHeight="11"
                :_class="
                  _fixed[0].sortType == 'desc' || _fixed[0].sortType == 'none'
                    ? ''
                    : 'opacity-6'
                "
                :font-size="20"
                name="tmicon-sort-down"
              ></tm-icon>
            </view>
          </view>
        </tm-sheet>
      </view>
      <scroll-view
        @scroll="tableScroll"
        @touchstart="scrollDong = 't'"
        @mouseup="scrollDong = 't'"
        class="flex-1"
        :class="['tableHeader']"
        :scroll-left="headerLeft"
        :scroll-x="true"
        :scroll-with-animation="false"
        :style="{
          width: `${
            defaultProps.width - (defaultProps.showFixed ? defaultProps.fixedWidth : 0)
          }rpx`,
        }"
        :show-scrollbar="false"
      >
        <view class="flex-1 flex flex-row flex-nowrap">
          <view v-for="(item, index) in _col" :key="index">
            <tm-sheet
              :border="_showBottomBorder ? 1 : 0"
              border-direction="bottom"
              :color="item.bgColor"
              :text="item.light"
              :_class="'flex flex-col ' + item.align"
              :height="defaultProps.headerHeight - 6"
              :width="item.width - 10"
              v-if="item.key != _fixedKey"
              :margin="[0, 0]"
              :padding="[10, 6]"
              @click="headerClick(item.key, item.sort)"
            >
              <view
                :style="{
                  width: item.width - 10 + 'rpx',
                  height: defaultProps.headerHeight - 6 + 'rpx',
                }"
                class="flex flex-row-center-center flex-row"
                :class="[item.align]"
              >
                <view @click.stop="" class="flex-1 flex-center" style="width: 0px">
                  <tm-text
                    @click="headerClick(item.key, item.sort)"
                    _style="line-height:normal;"
                    :font-size="26"
                    _class="text-weight-b text-align-center"
                    :label="item.title"
                  >
                  </tm-text>
                </view>
                <view
                  @click.stop=""
                  v-if="item.sort"
                  class="flex flex-col flex-col-center-center"
                >
                  <tm-icon
                    :lineHeight="11"
                    @click="headerClick(item.key, item.sort)"
                    :_class="
                      item.sortType == 'asce' || item.sortType == 'none'
                        ? ''
                        : 'opacity-6'
                    "
                    :font-size="20"
                    name="tmicon-sort-up"
                  ></tm-icon>
                  <tm-icon
                    :lineHeight="11"
                    @click="headerClick(item.key, item.sort)"
                    :_class="
                      item.sortType == 'desc' || item.sortType == 'none'
                        ? ''
                        : 'opacity-6'
                    "
                    :font-size="20"
                    name="tmicon-sort-down"
                  ></tm-icon>
                </view>
              </view>
            </tm-sheet>
          </view>
        </view>
      </scroll-view>
    </view>
    <view class="flex flex-row">
      <view v-if="_fixed.length > 1 && defaultProps.showFixed">
        <scroll-view
          @scroll="tableFixedScroll"
          :scroll-top="_fixedmenuTop"
          :scroll-y="true"
          :style="[
            defaultProps.height ? { height: `${defaultProps.height}rpx` } : '',
            { width: `${_fixed[0].width + 10}rpx` },
          ]"
        >
          <view v-for="(item, index) in _fixed" :key="index">
            <tm-sheet
              :border="_showBottomBorder ? 1 : 0"
              border-direction="bottom"
              v-if="index != 0"
              :color="item.bgColor"
              :text="item.light"
              :_class="'flex flex-col ' + item.align"
              :height="defaultProps.cellHeight - 6"
              :width="item.width - 10"
              :margin="[0, 0]"
              :padding="[10, 6]"
              @click="headerClick(item.key, item.sort)"
            >
              <view
                :userInteractionEnabled="false"
                :style="{
                  width: item.width - 10 + 'rpx',
                  height: defaultProps.cellHeight - 6 + 'rpx',
                }"
                class="flex flex-row-center-center flex-row"
                :class="[item.align]"
              >
                <view>
                  <tm-text
                    :font-size="26"
                    _class="text-weight-b text-align-center"
                    :label="item.title"
                  >
                  </tm-text>
                </view>
              </view>
            </tm-sheet>
          </view>
        </scroll-view>
      </view>

      <scroll-view
        class="flex-1"
        :scroll-with-animation="false"
        @scroll="headerScroll($event, 0)"
        @touchstart="touchStartScroll(0)"
        @mouseup="touchStartScroll(0)"
        :scroll-x="true"
        :scroll-y="true"
        :scroll-left="tableLeft[0]"
        :scroll-top="_fixedmenuTop"
        :style="[
          defaultProps.height ? { height: `${defaultProps.height}rpx` } : '',
          {
            width: `${
              defaultProps.width - (defaultProps.showFixed ? defaultProps.fixedWidth : 0)
            }rpx`,
          },
        ]"
      >
        <view
          class="flex flex-row flex-nowrap"
          style="white-space: nowrap"
          v-for="(item2, index2) in _tabel"
          :key="index2"
          :margin="[0, 0]"
        >
          <block v-for="(item, index) in item2.data" :key="index">
            <tm-sheet
              v-if="item.key != _fixedKey"
              :border="_showBottomBorder ? 1 : 0"
              border-direction="bottom"
              :key="index"
              :margin="[0, 0]"
              :color="item.color"
              :text="item.light"
              style="flex-shrink: 0"
              :_class="'flex flex-row ' + item2.align"
              :height="defaultProps.cellHeight - 6"
              :width="item.width - 10"
              :padding="[10, 6]"
            >
              <tm-text
                v-if="item.type == 'text'"
                :font-size="24"
                :label="item.text"
              ></tm-text>
              <tm-button
                @click="rowClick(index2, index)"
                :margin="[0, 0]"
                size="small"
                :color="_col[index]?.bgColor"
                :width="item.width - 16"
                v-if="item.type == 'button'"
                :font-size="24"
                :label="item.text"
              ></tm-button>
            </tm-sheet>
          </block>
        </view>
      </scroll-view>
    </view>
  </view>
  <!-- #endif -->
</template>

<script setup lang="ts">
// #ifdef APP-NVUE
import table from "./table.vue";
// #endif
// #ifndef APP-NVUE
import type { headresItem, cellItem, dataTypeArray } from "./interface";
import {
  computed,
  nextTick,
  onMounted,
  PropType,
  Ref,
  ref,
  toRaw,
  watchEffect,
  watch,
} from "vue";
import tmSheet from "../tm-sheet/tm-sheet.vue";
import tmText from "../tm-text/tm-text.vue";
import tmIcon from "../tm-icon/tm-icon.vue";
import tmButton from "../tm-button/tm-button.vue";
const emits = defineEmits(["rowClick"]);
const props = defineProps({
  showHeader: {
    type: Boolean,
    default: true,
  },
  header: {
    type: Array as PropType<Array<headresItem>>,
    default: () => [],
  },
  tableData: {
    type: Array as PropType<Array<cellItem>>,
    default: () => [],
    required: true,
  },
  width: {
    type: Number,
    default: 750,
  },
  fixedWidth: {
    type: Number,
    default: 200,
  },
  //如果提供了高度，将产生上下滑动的表格。
  height: {
    type: Number,
    default: 0,
  },
  //单元格的高度。
  cellHeight: {
    type: Number,
    default: 72,
  },
  //头部的高度。
  headerHeight: {
    type: Number,
    default: 88,
  },
  showBottomBorder: {
    type: Boolean,
    default: true,
  },
  showFixed: {
    type: Boolean,
    default: false,
  },
});
const defaultProps = computed(() => {
  return {
    width: props.width,
    height: props.height,
    cellHeight: props.cellHeight,
    headerHeight: props.headerHeight,
    fixedWidth: props.fixedWidth,
    showFixed: props.showFixed,
  };
});
const _col: Ref<Array<headresItem>> = ref([]);
const _tabel: Ref<Array<cellItem>> = ref([]);
const _fixed: Ref<Array<FixedItemType>> = ref([]);
const _fixedKey = ref("");
const _showBottomBorder = computed(() => props.showBottomBorder);
const _showHeader = computed(() => props.showHeader);
const _fixedmenuTop = ref(0);
const isNvue = ref(false);
// #ifdef APP-NVUE
isNvue.value = true;
// #endif
const headerLeft = ref(0);
const tableLeft: Ref<Array<number>> = ref([...new Array(props.tableData.length).fill(0)]);
let scrollDong = ref("");
let scrollIndex = ref(NaN);
function headerScroll(e: Event, index: number) {
  if (scrollDong.value != "h") return;
  nextTick(() => {
    _fixedmenuTop.value = Math.ceil(e.detail.scrollTop);
    headerLeft.value = e.detail.scrollLeft;
    tableLeft.value = tableLeft.value.map((el, idx) => {
      return idx !== index ? headerLeft.value : el;
    });
  });
}
function tableScroll(e: Event) {
  if (scrollDong.value != "t") return;
  nextTick(() => {
    tableLeft.value = [...new Array(props.tableData.length).fill(e.detail.scrollLeft)];
  });
}

function touchStartScroll(index) {
  scrollIndex.value = index;
  scrollDong.value = "h";
}

function tableFixedScroll(e) {
  _fixedmenuTop.value = Math.ceil(e.detail.scrollTop);
}
onMounted(() => {
  nextTick(() => setColData());
});
watch(
  [() => props.tableData, () => props.header],
  () => {
    setColData();
  },
  { deep: true }
);
function setColData() {
  _col.value = [];
  _tabel.value = [];
  _fixed.value = [];
  let defaultSort = "none";
  props.header.forEach((el, index) => {
    //这里的目的是，当有一列数据默认有排序，那么它后面全部默认都不能排序了，只能优先排序第一个数据。后期需要界面点击切换。
    let defaultSort = el?.sortType ?? "none";
    if (defaultSort != "none") {
      defaultSort = "none";
    }
    let isFixed = el?.fixed ?? false;
    _col.value.push({
      title: el?.title ?? "",
      width: el?.width ?? 145,
      align: "flex-row-center-" + (el?.align || "center"),
      sort: el?.sort ?? false,
      bgColor: el?.bgColor ?? "white",
      cellColor: el?.cellColor ?? "white",
      light: el?.light ?? false,
      key: el?.key ?? String(index),
      fixed: isFixed,
      sortType: defaultSort,
    });
  });

  props.tableData.forEach((el, index) => {
    let d = el?.data ?? {};
    let keys = Object.keys(d);
    for (let ik = 0, len = keys.length; ik < len; ik++) {
      if (typeof _col.value[ik] == "undefined") {
        _col.value.push({
          title: String(ik),
          width: el?.width ?? 145,
          align: "flex-col-center-" + (el?.align || "center"),
          sort: false,
          bgColor: "white",
          cellColor: "white",
          light: false,
          key: String(ik),
          fixed: false,
          sortType: "none",
        });
      }
    }
    let dataRuslt: Array<dataTypeArray> = [];
    _col.value.forEach((el2, index) => {
      let color = "white";
      let light = false;
      if (typeof d[el2.key] !== "object") {
        color = el?.color || _col.value[index]?.cellColor || color;
        light = el?.light || _col.value[index]?.light || light;
      } else {
        color = d[el2.key]?.color || el?.color || _col.value[index]?.color || color;
        light = d[el2.key]?.light || el?.light || _col.value[index]?.light || light;
      }
      let cel: dataTypeArray = {
        key: el2.key,
        text: typeof d[el2.key] !== "object" ? d[el2.key] : d[el2.key]?.text ?? "",
        type: typeof d[el2.key] !== "object" ? "text" : d[el2.key]?.type ?? "text",
        width: _col.value[index]?.width ?? 145,
        light: light,
        color: color,
        fixed: typeof d[el2.key] !== "object" ? false : d[el2.key]?.fixed ?? false,
      };
      if (typeof d[el.key] === "object") {
        cel = { ...cel, ...d[el.key] };
      }

      dataRuslt.push(cel);
    });
    _tabel.value.push({
      data: dataRuslt,
      align: el?.align ?? _col.value[index]?.align ?? "flex-row-center-center",
      key: el?.key ?? String(index),
    });
  });

  // 检查是否固定在左侧的内容。头和数据。
  let headerIndex = 0;
  let headerIndexFixed = _col.value.find((el, index) => {
    headerIndex = index;
    return el.fixed == true;
  });
  if (typeof headerIndexFixed !== "undefined") {
    let headerkey = headerIndexFixed.key;
    _fixedKey.value = headerkey;
    _fixed.value.push({ ...headerIndexFixed });
    let cellIndex = 0;
    _tabel.value.forEach((el, index2) => {
      el.data.forEach((cel, index) => {
        if (cel.key == headerkey) {
          _fixed.value.push({
            title: cel.text,
            key: cel?.key ?? String(index2 + 1),
            width: cel.width,
            align: headerIndexFixed?.align ?? "flex-row-center-center",
            sort: false, //是否显示排序,默认false
            bgColor: cel.color ?? "", //当前头的背景色。默认grey
            cellColor: cel.color ?? "", //当前列的背景色。,如果为"",则使用行数据的背景，如果行背景也没有提供，使用white.
            light: cel.light ?? false, //背景色是否是浅色
            sortType: "", //desc降序，升序asce,none,无排序
            fixed: true, //是否固定在左侧端
          });
        }
      });
    });
  }
}
function headerClick(key: string, isSort = false) {
  if (!isSort) return;
  let valueArray = _col.value.filter((el) => el.key == key);
  let keyDesc = valueArray[0].sortType;
  if (!keyDesc || keyDesc == "none") {
    sort(key, "desc");
    return;
  }
  if (keyDesc == "none") {
    sort(key, "desc");
    return;
  }
  if (keyDesc == "desc") {
    sort(key, "asce");
    return;
  }
  if (keyDesc == "asce") {
    sort(key, "none");
    return;
  }
}
//descKey需要排序的字段。
function sort(descKey = "", type = "none") {
  uni.showLoading({
    title: "...",
    mask: true,
  });
  // 排序
  if (type == "none" || descKey === "") {
    setColData();
    uni.hideLoading();
    return;
  }
  let lsTemp = _tabel.value.map((item, index) => {
    let valueArray = item.data.filter((el) => el.key == descKey);
    return {
      oldIndex: index,
      value: valueArray[0].text,
    };
  });

  //降序
  if (type == "desc") {
    lsTemp.sort((a, b) => a.value - b.value);
  }
  //升序。
  if (type == "asce") {
    lsTemp.sort((a, b) => b.value - a.value);
  }
  const backTable = toRaw(_tabel.value);

  nextTick(() => {
    _col.value = _col.value.map((el) => {
      return { ...el, sortType: el.key == descKey ? type : el.sortType };
    });
    _tabel.value = lsTemp.map((el) => {
      return backTable[el.oldIndex];
    });
    uni.hideLoading();
  });
}

function rowClick(rowIndex: number, colIndex: number) {
  emits("rowClick", rowIndex, colIndex);
}

// #endif
</script>

<style></style>
